package com.s20y.generator.utils;

import com.google.common.base.CaseFormat;
import com.s20y.generator.entity.Column;
import com.s20y.generator.entity.Table;
import com.s20y.generator.entity.TempletPathInfo;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
public class GeneratorUtil {
    private static Configuration config = new Configuration();
    private static Map<String, Object> params = new HashMap<>();
    private static PropertiesConfiguration pConfig;

    static {
        try {
            pConfig = new PropertiesConfiguration("generator.properties");
        } catch (ConfigurationException e) {
            log.error("没有找到generator.properties文件");
        }
    }

    public static void generatorCode(Table table, TempletPathInfo pathInfo) {
        params.put("table", table);
        params.put("author", table.getAuthor());
        params.put("package", table.getPackagePath());
        config.setClassLoaderForTemplateLoading(ClassLoader.getSystemClassLoader(), "/templates/generator");
        Map autoImportsMap = new HashMap();
        autoImportsMap.put("m", "macro.ftl");
        config.setAutoImports(autoImportsMap);

        Template template = null;
        try {
            template = config.getTemplate(pathInfo.getFileName());
        } catch (IOException e) {
            log.error("无法加载模板：{}", pathInfo.getFileName());
        }

        File outFile = new File(pathInfo.getFullPath(table.getOutRootPath(), table.getName()));
        try {
            generatorFile(template, params, outFile);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (TemplateException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据模板以及配置信息生产文件
     *
     * @param template 模板
     * @param params   传递给模板的值
     * @param file     输出文件
     */
    private static void generatorFile(Template template, Map<String, Object> params, File file) throws IOException, TemplateException {
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }
        Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        template.process(params, writer);
        log.info("生成文件：{}", file.getPath());
        writer.flush();
        writer.close();
    }

    /**
     * 重载补全table信息
     *
     * @param table
     */
    public static void formatTable(Table table) {
        String name;
        if ("CAMEL_CASE".equals(table.getNameCast())) {
            name = table.getTableName();
        } else {
            name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_CAMEL, table.getTableName());
        }
        table.setName(name);
        table.setSerialUID(new Date().getTime() + "L");
        formatColumn(table);
    }

    /**
     * 重载补全columns信息
     *
     * @param table
     */
    private static void formatColumn(Table table) {
        List<Column> updateColumns = table.getUpdateColumns();
        for (Column column : table.getColumns()) {
            column.setJavaType(pConfig.getString(column.getJdbcType()));
            if ("id".equals(column.getColumnName())) {
                table.setIdJavaType(column.getJavaType());
            }
            String name;
            if ("CAMEL_CASE".equals(table.getNameCast())) {
                name = column.getColumnName();
            } else {
                name = CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, column.getColumnName());
            }
            column.setName(name);

            List noNeedUpdateList = CollectionUtils.arrayToList("id,createTime,updateTime".split(","));
            if (!noNeedUpdateList.contains(name)) {
                updateColumns.add(column);
            }

            List ignoredList = CollectionUtils.arrayToList("id,createBy,createTime,updateBy,updateTime,summary".split(","));
            if (ignoredList.contains(name)) {
                column.setIsIgnored(Boolean.TRUE);
            } else {
                if (column.getJavaType().equals("BigDecimal")) {
                    table.setHasBigDecimal(Boolean.TRUE);
                }
                if (column.getJavaType().equals("LocalDate")) {
                    table.setHasDate(Boolean.TRUE);
                }
                if (column.getJavaType().equals("LocalTime")) {
                    table.setHasTime(Boolean.TRUE);
                }
                if (column.getJavaType().equals("LocalDateTime")) {
                    table.setHasDateTime(Boolean.TRUE);
                }
                if (column.getJavaType().equals("JSONObject")) {
                    table.setHasJSONObject(Boolean.TRUE);
                }
            }
        }
    }
}